import { Constant, InvokeExpr, Variable } from 'qvog-types';
import { P, Q, ValuePredicate } from '~/core/dsl/Predicates';
import { pattern } from '~/core/dsl/fluent/QueryDescriptor';

const SensitiveItems = ['password', 'pwd'];

export const SensitiveLocalStorageRule = pattern('@security/sensitive-localstorage', (q) =>
    q
        .from((f) => f.withData((v) => v.stream().any(Q(InvokeExpr))).as('localStorage'))
        .where((f) =>
            f.on('localStorage').where(
                ValuePredicate.of((value) =>
                    value.stream().any(
                        Q(
                            InvokeExpr,
                            P<InvokeExpr>((v) => v.target === 'setItem')
                                .and<Variable>(
                                    (v) => v.name === 'localStorage',
                                    (v) => v.base! as Variable,
                                    Variable
                                )
                                .and((v) => v.argCount === 2)
                                .and<Constant>(
                                    (v) => SensitiveItems.includes(v.stringValue),
                                    (s) => s.args[0] as Constant,
                                    Constant
                                )
                                .done()
                        )
                    )
                )
            )
        )
        .select('localStorage', '`localStorage` is used to store sensitive information')
);
